package com.eu.ebpm.engine.service.impl;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.eu.ebpm.engine.cmd.RevokeTaskSignCommand;
import com.eu.ebpm.engine.cmd.SetForkVariableCommand;
import com.eu.ebpm.engine.cmd.SetParentForkVariableCommand;
import com.eu.ebpm.engine.cmd.TaskClaimCommand;
import com.eu.ebpm.engine.entity.deploy.Mission;
import com.eu.ebpm.engine.entity.runtime.TaskEntity;
import com.eu.ebpm.engine.exception.ErrorCode;
import com.eu.ebpm.engine.exception.WorkFlowException;
import com.eu.ebpm.engine.init.EbpmCache;
import com.eu.ebpm.engine.pvm.PvmContainer;
import com.eu.ebpm.engine.query.TaskQuery;
import com.eu.ebpm.engine.query.TaskQueryImpl;
import com.eu.ebpm.engine.repository.TaskRepository;
import com.eu.ebpm.engine.service.Task;
import com.eu.ebpm.engine.service.TaskService;

@Service
@Transactional
public class TaskServiceImpl implements TaskService {

	@Autowired
	private PvmContainer pvmContainer;
	
	@Autowired
	private RevokeTaskSignCommand taskUnClaimCommand;
	
	@Autowired
	private TaskClaimCommand taskClaimCommand;
	
	@Autowired
	private SetParentForkVariableCommand setParentForkVariableCommand;
	
	@Autowired
	private SetForkVariableCommand setForkVariableCommand;
	
	@Autowired
	private TaskRepository taskRepository;

	public void sign(long taskId, String assignee) {
		taskClaimCommand.execute(assignee, taskId);
	}

	public void complete(long taskId) {
		complete(taskId, null, null);
	}
	
	public void complete(long taskId, String remark) {
		complete(taskId, null, remark);
	}

	public void complete(long taskId, Map<String, Object> variables) {
		complete(taskId, variables, null);
	}

	public void complete(long taskId, Map<String, Object> variables, String remark) {

		TaskEntity task = taskRepository.queryById(taskId);
		
		if(task == null) {
			throw new WorkFlowException(String.format("任务[%d]不存在或者已经被执行", taskId));
		}

		if (task.getAssignee() == null) {
			throw new WorkFlowException(ErrorCode.RU_NOT_SIGN);
		}
		
		task.setRemark(remark);

		// 1、拿到任务定义
		Mission mission = EbpmCache.getMission(task.getMissionId());

		// 2、根据任务类型、提交任务
		pvmContainer.getPvmService(mission.getType()).complete(mission, task, variables);
	}

	@Transactional(readOnly=true)
	public TaskQuery createQuery() {
		return new TaskQueryImpl();
	}

	/**
	 * complete时，直接设置参数即可
	 */
	@Deprecated
	public void setForkVariable(long taskId, Map<String, Object> variables) {
		setForkVariableCommand.execute(taskId, variables);
	}

	/**
	 * 此方法存在场景： 子流程在父流程fork节点中，需要设置父流程fork节点的执行参数。故需要往父节点设置参数。
	 */
	public void setParentForkVariable(long taskId, Map<String, Object> variables) {
		setParentForkVariableCommand.execute(taskId, variables);
	}

	public void unSign(Task task) {
		taskUnClaimCommand.execute(task);
	}

}
